/**
 * @file kprint.c
 * @author DY Young (dyyoung@os.email.cn)
 * @brief format string output is implemented
 *        in this file. And the output is directed to
 *        serial by device manager.
 * @version 0.1
 * @date 2023-07-01
 *
 * @copyright Copyright (c) 2023
 *
 */

#include "kstdio.h"
#include "strapi.h"
#include "astralapi.h"


#define MAX_BUFFER_SIZE 512
struct AstralSpin kprint_spin;


int kvdnprintf(const char* dev_name, char *buffer, int length)
{
    int actual = 0;
    AstralDevice out = open_device(dev_name);
    if(!out)
    {
        return 0;
    }
    if(out->status != OPENED)
    {
        out->status = OPENED;
        out->operations->dopen(out, NULL);
    }

    out->operations->dwrite(out, buffer, length, &actual);
    return actual;
}

void kprint(const char *fmt, ...)
{
    static char buffer[MAX_BUFFER_SIZE];

    word irqstatus;
    irqstatus = spin_lock_irq(&kprint_spin);

    va_list args;
    va_start(args, fmt);
    vsnprintf(buffer, MAX_BUFFER_SIZE, fmt, args);
    va_end(args);

    kvdnprintf("tty0", buffer, MAX_BUFFER_SIZE);
    kvdnprintf("terminal", buffer, MAX_BUFFER_SIZE);

    spin_unlock_irq(&kprint_spin, irqstatus);
}


void kerror(const char *fmt, ...)
{
    char buffer[MAX_BUFFER_SIZE];

    va_list args;
    va_start(args, fmt);
    vsnprintf(buffer, MAX_BUFFER_SIZE, fmt, args);
    va_end(args);

    kprint("\033[5m\033[91m%s\033[0m", buffer);
}



void kscan(char *stream)
{
    *stream = '\0';
    boolean stoped = False;
    for (int i = 0; i < MAX_BUFFER_SIZE;)
    {
        char c = getc_from_kstdin();
        switch (c)
        {
        case '\n':
        case '\r':
            *(stream + i) = '\0';
            stoped = True;
            break;
        case 9: //Tab
            break;
        case 8: //backspace
        case 127: // DEL
            i = i > 1 ? i - 1 : 0;
            continue;
        default:
            *(stream + i) = c;
            i++;
            break;
        }
        if (stoped)
        {
            break;
        }
    }
}